package com.faxsun.core.pricing.service.fulfillment.provider;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.broadleafcommerce.common.money.Money;
import org.broadleafcommerce.common.vendor.service.exception.FulfillmentPriceException;
import org.broadleafcommerce.core.order.domain.FulfillmentGroup;
import org.broadleafcommerce.core.order.domain.FulfillmentGroupItem;
import org.broadleafcommerce.core.order.domain.FulfillmentOption;
import org.broadleafcommerce.core.order.fulfillment.domain.FixedPriceFulfillmentOption;
import org.broadleafcommerce.core.order.service.FulfillmentOptionService;
import org.broadleafcommerce.core.pricing.service.fulfillment.provider.FulfillmentEstimationResponse;
import org.broadleafcommerce.core.pricing.service.fulfillment.provider.FulfillmentPricingProvider;

import com.faxsun.core.catalog.domain.FSProductImpl;
import com.faxsun.core.catalog.domain.FSSku;
import com.faxsun.core.order.domain.FSOrderItemImpl;
import com.faxsun.core.pricing.service.fulfillment.calculator.ShippmentFeeCalculator;

public class InternationalShippmentProvider implements FulfillmentPricingProvider {

	@Resource(name = "blFulfillmentOptionService")
	protected FulfillmentOptionService fulfillmentOptionService;
	
	@Resource
	protected ShippmentFeeCalculator calculator;

	@Override
	public FulfillmentGroup calculateCostForFulfillmentGroup(FulfillmentGroup fulfillmentGroup) throws FulfillmentPriceException {
		Money fulfillmentCharges = calculatePrices(fulfillmentGroup);

		// optionally set the retailPrice and salePrice of the fulfillment group
		// fulfillmentGroup.setRetailFulfillmentPrice(fullPriceOfFulfillmentGroup);
		// fulfillmentGroup.setSaleFulfillmentPrice(discountedPriceOfFulfillmentGroup);

		// REQUIRED
		fulfillmentGroup.setFulfillmentPrice(fulfillmentCharges);
		return fulfillmentGroup;
	}

	private Money calculatePrices(FulfillmentGroup fulfillmentGroup) {
		// TODO: To be implemented in ShippmentFeeCalculator
		// FIXME: Yet clear to know how to deal with products without weight
		List<FulfillmentGroupItem> items = fulfillmentGroup.getFulfillmentGroupItems();
		List<FulfillmentOption> allOptions = fulfillmentOptionService.readAllFulfillmentOptions();

		Map<String, Money> candiataShippingFees = new HashMap<String, Money>();
	
		for (FulfillmentOption option : allOptions) {
			String countryCode = option.getLongDescription();
			String categoryId = option.getName();
			Money price = ((FixedPriceFulfillmentOption) option).getPrice();

			candiataShippingFees.put(countryCode + "_" + categoryId, price);
		}	 

		Money totalShippingFee = Money.ZERO;

		for (FulfillmentGroupItem item : items) {
			FSOrderItemImpl orderItem = (FSOrderItemImpl) item.getOrderItem();
			FSProductImpl product = (FSProductImpl) orderItem.getProduct();

			int quantity = item.getQuantity();
			FSSku sku = (FSSku) orderItem.getSku();
			totalShippingFee=totalShippingFee.add(this.calculator.calculateShippmentFeeBySku(sku, quantity));
				
		}

		return totalShippingFee;
	}

	@Override
	public boolean canCalculateCostForFulfillmentGroup(FulfillmentGroup fulfillmentGroup, FulfillmentOption option) {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public FulfillmentEstimationResponse estimateCostForFulfillmentGroup(FulfillmentGroup fulfillmentGroup,
			Set<FulfillmentOption> options) throws FulfillmentPriceException {
		FulfillmentEstimationResponse response = new FulfillmentEstimationResponse();
		HashMap<FulfillmentOption, Money> shippingPrices = new HashMap<FulfillmentOption, Money>();
		response.setFulfillmentOptionPrices(shippingPrices);

		for (FulfillmentOption option : options) {
			if (canCalculateCostForFulfillmentGroup(fulfillmentGroup, option)) {
				Money price = ((FixedPriceFulfillmentOption) option).getPrice();
				shippingPrices.put(option, price);
			}
		}

		return response;
	}

}
